﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"

namespace gnuf {
    class Item;
    class ButtonControl;
    class ButtonToolDefinition;
    
    //
    // ButtonControlTracker intends to track the triggered button by HotKey or
    // clicking explicitly. Two important concecpts (Scenario and Context) were
    // introduced.
    // 
    // Scenario just is the environment in which the user works. For example,
    // when enter a edit mode, a new scenario will start up. Later, when leave
    // from the edit mode, this scenario will end up. We're using a stack to
    // manage those scenarios.
    //
    // Inside of a Scenario, the user might enter a transient context. For example,
    // when an element selected, a dynamic panel will present some buttons that
    // help to edit the selected. Later, when it unselected, the dynamic panel gets
    // clear. Context intends to track the buttons, during this workflow. So that,
    // this element is selected, again, the user easily sees this last button.
    //
    // The caller has to determine to track the triggered button inside of the
    // top Scenario or/and the current context.
    //
    // - frank 08/27/2021
    //     
    
    class GNUF_BASE_EXPORT ButtonControlTracker final
    {
        CANNOT_COPY_OR_ASSIGN(ButtonControlTracker)
    public:
        ButtonControlTracker();
        ~ButtonControlTracker();

        static ButtonControlTracker * get();

        // Track
        void trackInScenario(const Item *, const bool wantToAffectContext);
        void trackInScenario(ButtonControl *, const bool wantToAffectContext);
        void trackInContext(const Item *, const gcmp::UniqueString *, const std::wstring & contextId);

        void setCurrentContextId(const std::wstring & val);
        const std::wstring & currentContextId() const { return m_currentContextId; }
        void clearCurrentContextId();

        // Click on the last button if existed and enabled.
        bool clickLastButton();

        // Return ture if the last button is existed, enabled and visible. 
        // Otherwise, return false.
        bool isLastButtonValid() const;

        // Return ture if existed. Otherwise, return false.
        bool doesLastButtonExist(const std::wstring ** ppCaption = nullptr) const;

        // Clear all the tracking information in both Scenarios and Contexts.
        void clear();

    private:
        ButtonToolDefinition * lastButton() const;
        
        typedef std::map<
            std::wstring,   // Context ID
            std::wstring    // Button Tool Definition Key
        > Context;          // A button tool definition key per context
        typedef std::map< const gcmp::UniqueString *, Context > Contexts;
        
        std::wstring m_currentContextId;
        ButtonControlTracker::Contexts m_contexts;
    };
    
}
